package com.blog.blog.service.impl;

import com.blog.blog.mapper.PermissionMapper;
import com.blog.blog.mapper.UserMapper;
import com.blog.blog.mapper.RoleMapper;
import com.blog.blog.mapper.OperationLogMapper;
import com.blog.blog.mapper.SystemConfigMapper;
import com.blog.blog.service.SystemService;
import com.blog.blog.vo.PermissionVO;
import com.blog.blog.vo.RoleVO;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SystemServiceImpl implements SystemService {

    private final RoleMapper roleMapper;
    private final PermissionMapper permissionMapper;
    private final UserMapper userMapper;
    private final OperationLogMapper operationLogMapper;
    private final SystemConfigMapper systemConfigMapper;
    private final org.springframework.data.redis.core.StringRedisTemplate stringRedisTemplate;

    public SystemServiceImpl(RoleMapper roleMapper,
                             PermissionMapper permissionMapper,
                             UserMapper userMapper,
                             OperationLogMapper operationLogMapper,
                             SystemConfigMapper systemConfigMapper,
                             org.springframework.data.redis.core.StringRedisTemplate stringRedisTemplate) {
        this.roleMapper = roleMapper;
        this.permissionMapper = permissionMapper;
        this.userMapper = userMapper;
        this.operationLogMapper = operationLogMapper;
        this.systemConfigMapper = systemConfigMapper;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public List<RoleVO> listRoles(String keyword) {
        return roleMapper.listRoles(keyword);
    }

    @Override
    public List<PermissionVO> listPermissions(String keyword) {
        return permissionMapper.listPermissions(keyword);
    }

    @Override
    public Long createRole(com.blog.blog.dto.SaveRoleDTO dto) {
        int n = roleMapper.insertRole(dto);
        if (n > 0) {
            // MySQL 自增ID可通过 select 获取，这里简化：返回 null 代表需前端刷新
            return null;
        }
        return null;
    }

    @Override
    public boolean updateRole(Long id, com.blog.blog.dto.SaveRoleDTO dto) {
        return roleMapper.updateRole(id, dto) > 0;
    }

    @Override
    public boolean deleteRole(Long id) {
        return roleMapper.deleteRole(id) > 0;
    }

    @Override
    public Long createPermission(com.blog.blog.dto.SavePermissionDTO dto) {
        int n = permissionMapper.insertPermission(dto);
        if (n > 0) {
            // 插入成功，返回一个标识（这里简化返回1L，实际项目中可以返回自增ID）
            return 1L;
        }
        throw new RuntimeException("权限创建失败");
    }

    @Override
    public boolean updatePermission(Long id, com.blog.blog.dto.SavePermissionDTO dto) {
        return permissionMapper.updatePermission(id, dto) > 0;
    }

    @Override
    public boolean deletePermission(Long id) {
        return permissionMapper.deletePermission(id) > 0;
    }

    @Override
    public boolean setRolePerms(Long roleId, java.util.List<Long> permIds) {
        roleMapper.deleteRolePerms(roleId);
        if (permIds != null) {
            for (Long pid : permIds) {
                if (pid != null) roleMapper.insertRolePerm(roleId, pid);
            }
        }
        return true;
    }

    @Override
    public java.util.List<Long> getRolePermIds(Long roleId) {
        return roleMapper.selectPermIdsByRoleId(roleId);
    }

    @Override
    public java.util.List<Long> getUserRoleIds(Long userId) {
        return userMapper.selectRoleIdsByUserId(userId);
    }

    @Override
    public boolean setUserRoles(Long userId, java.util.List<Long> roleIds) {
        userMapper.deleteUserRoles(userId);
        if (roleIds != null) {
            for (Long rid : roleIds) {
                if (rid != null) userMapper.insertUserRole(userId, rid);
            }
        }
        return true;
    }

    @Override
    public com.blog.blog.common.PageResponse<com.blog.blog.po.UserPO> pageUsers(String q, Integer pageNo, Integer pageSize) {
        int p = (pageNo == null || pageNo < 1) ? 1 : pageNo;
        int s = (pageSize == null || pageSize < 1) ? 10 : Math.min(pageSize, 100);
        int offset = (p - 1) * s;
        long total = userMapper.countUsers(q);
        java.util.List<com.blog.blog.po.UserPO> records = userMapper.pageUsers(q, offset, s);
        return new com.blog.blog.common.PageResponse<>(total, records);
    }

    @Override
    public boolean isSelfDataScope(Long userId) {
        if (userId == null) return false;
        java.util.List<String> scopes = roleMapper.selectRoleDataScopesByUserId(userId);
        if (scopes == null || scopes.isEmpty()) return true; // 未分配角色，按 SELF 处理
        for (String s : scopes) {
            if (s != null && s.equalsIgnoreCase("ALL")) return false;
        }
        return true;
    }

    @Override
    public com.blog.blog.common.PageResponse<com.blog.blog.vo.OperationLogVO> pageOperationLogs(String q, Integer status, Integer pageNo, Integer pageSize) {
        int p = (pageNo == null || pageNo < 1) ? 1 : pageNo;
        int s = (pageSize == null || pageSize < 1) ? 10 : Math.min(pageSize, 100);
        int offset = (p - 1) * s;
        long total = operationLogMapper.countLogs(q, status);
        java.util.List<com.blog.blog.vo.OperationLogVO> records = operationLogMapper.pageLogs(q, status, offset, s);
        return new com.blog.blog.common.PageResponse<>(total, records);
    }

    // 系统配置
    @Override
    public java.util.List<com.blog.blog.vo.SystemConfigVO> listConfigs(String prefix) {
        return systemConfigMapper.listConfigs(prefix);
    }

    @Override
    public boolean upsertConfig(String key, String value, String description) {
        if (key == null || key.isBlank()) return false;
        int n = systemConfigMapper.upsertConfig(key, value, description);
        return n > 0;
    }

    // 缓存管理（Redis）
    @Override
    public java.util.List<String> scanRedisKeys(String pattern, Integer limit) {
        String p = (pattern == null || pattern.isBlank()) ? "*" : pattern;
        int max = (limit == null || limit < 1) ? 200 : Math.min(limit, 1000);
        java.util.List<String> result = stringRedisTemplate.execute((org.springframework.data.redis.core.RedisCallback<java.util.List<String>>) connection -> {
            java.util.List<String> keys = new java.util.ArrayList<>();
            org.springframework.data.redis.core.ScanOptions options = org.springframework.data.redis.core.ScanOptions.scanOptions().match(p).count(500).build();
            try (org.springframework.data.redis.core.Cursor<byte[]> cursor = connection.keyCommands().scan(options)) {
                while (cursor.hasNext() && keys.size() < max) {
                    keys.add(new String(cursor.next()));
                }
            } catch (Exception ignored) { }
            return keys;
        });
        return result == null ? java.util.Collections.emptyList() : result;
    }

    @Override
    public long deleteRedisKeysByPattern(String pattern) {
        String p = (pattern == null || pattern.isBlank()) ? "*" : pattern;
        java.util.Set<String> ks = stringRedisTemplate.keys(p);
        if (ks == null || ks.isEmpty()) return 0L;
        return stringRedisTemplate.delete(ks);
    }

    @Override
    public boolean redisPing() {
        try {
            String pong = stringRedisTemplate.getRequiredConnectionFactory().getConnection().ping();
            return pong != null && !pong.isBlank();
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public java.util.List<com.blog.blog.vo.OnlineSessionVO> listOnlineSessions(String q) {
        java.util.List<String> keys = stringRedisTemplate.execute((org.springframework.data.redis.core.RedisCallback<java.util.List<String>>) connection -> {
            java.util.List<String> out = new java.util.ArrayList<>();
            org.springframework.data.redis.core.ScanOptions options = org.springframework.data.redis.core.ScanOptions.scanOptions().match("auth:token:*").count(500).build();
            try (org.springframework.data.redis.core.Cursor<byte[]> cursor = connection.keyCommands().scan(options)) {
                while (cursor.hasNext()) {
                    out.add(new String(cursor.next()));
                }
            } catch (Exception ignored) {}
            return out;
        });
        java.util.List<com.blog.blog.vo.OnlineSessionVO> list = new java.util.ArrayList<>();
        if (keys == null) return list;
        for (String k : keys) {
            String v = stringRedisTemplate.opsForValue().get(k);
            Long ttl = stringRedisTemplate.getExpire(k, java.util.concurrent.TimeUnit.SECONDS);
            if (v == null) continue;
            String[] arr = v.split("\\|");
            if (arr.length >= 2) {
                com.blog.blog.vo.OnlineSessionVO vo = new com.blog.blog.vo.OnlineSessionVO();
                vo.setToken(k.substring("auth:token:".length()));
                try { vo.setUserId(Long.parseLong(arr[0])); } catch (Exception ignored) {}
                vo.setRoles(arr[1]);
                vo.setTtlSeconds(ttl);
                com.blog.blog.po.UserPO u = userMapper.selectById(vo.getUserId());
                if (u != null) vo.setUsername(u.getUsername());
                if (q == null || q.isBlank() || (vo.getUsername() != null && vo.getUsername().contains(q))) {
                    list.add(vo);
                }
            }
        }
        list.sort((a,b) -> Long.compare(b.getTtlSeconds() == null ? -1 : b.getTtlSeconds(), a.getTtlSeconds() == null ? -1 : a.getTtlSeconds()));
        return list;
    }

    @Override
    public boolean kickoutToken(String token) {
        if (token == null || token.isBlank()) return false;
        return Boolean.TRUE.equals(stringRedisTemplate.delete("auth:token:" + token));
    }
}


